{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1330548c-77ed-43ba-a41e-ff3eb8351dd0",
   "metadata": {},
   "source": [
    "## 如何要进行矢量数据空间分析，一般转成EPSG:3857的投影坐标系【单位为米】会接近于实际情况的思维方式"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5531baa9-d80a-464c-b04a-a2ca9cf8baa0",
   "metadata": {},
   "source": [
    "### 1.封装坐标转换函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2dd848e-b466-4f9d-ac62-ba31ba95491d",
   "metadata": {},
   "source": [
    "#### 1.1单个数据转投影函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "543a33dc-3720-45a2-8374-6bda7f766d8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import geopandas as gpd\n",
    "import os\n",
    "\n",
    "\"\"\"\n",
    "单个文件坐标转换函数\n",
    "\"\"\"\n",
    "def TransferProjByEPSG(vector_file_path,target_epsg):\n",
    "    try:\n",
    "        # 读取一个已有的矢量数据文件，假设其具有坐标参考系信息\n",
    "        gdf = gpd.read_file(vector_file_path)\n",
    "\n",
    "        # 查看原始数据的坐标系\n",
    "        print(f\"正在处理文件 {vector_file_path}，原始数据的坐标系:\", gdf.crs)\n",
    "        # 查看原始数据的坐标系\n",
    "        print(\"原始数据的坐标系:\", gdf.crs)\n",
    "\n",
    "        if(gdf.crs != target_epsg):\n",
    "            # 将坐标参考系转换为EPSG指定code\n",
    "            gdf_transformed = gdf.to_crs(target_epsg) #格式举例：'EPSG:3857'\n",
    "            # 查看转换后的数据的坐标系\n",
    "            print(\"转换后数据的坐标系:\", gdf_transformed.crs)\n",
    "        \n",
    "             # 获取输出文件所在的文件夹路径（与输入文件在同一文件夹）\n",
    "            output_folder = os.path.dirname(vector_file_path)\n",
    "            # 获取输入文件名（包含路径）\n",
    "            input_file_name = os.path.basename(vector_file_path)\n",
    "            # 获取文件名（不含路径和扩展名）\n",
    "            base_name = os.path.splitext(input_file_name)[0]\n",
    "            # 构建输出文件名，在原文件名后加上目标EPSG编号\n",
    "            output_file_name = base_name + '_' + target_epsg.split(':')[-1] + '.shp'\n",
    "           \n",
    "            # 构建完整的输出文件路径\n",
    "            output_file_path = os.path.join(output_folder, output_file_name)\n",
    "            \n",
    "            # 保存转换后的矢量数据为新的文件\n",
    "            gdf_transformed.to_file(output_file_path)\n",
    "            print(f\"已将 {vector_file_path} 转换后的文件保存至 {output_file_path}\")\n",
    "        else:\n",
    "            print(f\" {vector_file_path} 的坐标系和目标坐标系相同，无需转换\")\n",
    "    except Exception as e:\n",
    "        print(f\"处理文件 {vector_file_path} 时出错，错误信息: {e}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c37e6ecf-bfd4-403d-b4b5-50b1df4e8be3",
   "metadata": {},
   "source": [
    "#### 1.2批量转投影"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "a24ad088-4a03-4e47-ac67-3f7fe3d59630",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "判断文件路径中是否包含目标EPSG编号，以此来判断文件是否已是目标投影。\n",
    "\"\"\"\n",
    "def is_target_projection(file_path, target_epsg):\n",
    "    return target_epsg.split(':')[-1] in file_path\n",
    "\n",
    "\"\"\"\n",
    "批量转投影函数\n",
    "\"\"\"\n",
    "def batch_TransferProjByEPSG(input_folder,target_epsg):\n",
    "    \n",
    "    # 遍历文件夹及其子文件夹下的所有文件\n",
    "    for root, dirs, files in os.walk(input_folder):\n",
    "        for file in files:\n",
    "            if file.endswith('.shp'):\n",
    "                # 获取输入文件的完整路径\n",
    "                vector_file_path = os.path.join(root, file)\n",
    "                # 获取输出文件名（在原文件名基础上加上目标EPSG编号）\n",
    "                input_file_name = os.path.basename(vector_file_path)\n",
    "                base_name = os.path.splitext(input_file_name)[0]\n",
    "                # epsg参数中的数字部分\n",
    "                epsg_num = target_epsg.split(':')[-1] \n",
    "                output_file_name = base_name + '_' + epsg_num + '.shp'\n",
    "                output_file_path = os.path.join(root, output_file_name)\n",
    "    \n",
    "                # 判断输出文件是否已存在或者文件已是目标投影，如果满足则跳过该文件的投影转换\n",
    "                if os.path.exists(output_file_path) or is_target_projection(vector_file_path, target_epsg):\n",
    "                    print(f\"{vector_file_path} 已满足目标投影相关条件，跳过该文件的投影转换。\")\n",
    "                    continue   \n",
    "                TransferProjByEPSG(vector_file_path,target_epsg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53a48eb5-7b4f-4034-99ef-728ae6a65ff9",
   "metadata": {},
   "source": [
    "### 2.选择需要转投影的数据进行转投影"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab8f06be-27af-4532-aeaa-dc0c5d5fce88",
   "metadata": {},
   "source": [
    "#### 2.1武昌区行政边界"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "95c14cf3-39d8-4b8a-a77f-d34e58ee83a1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在处理文件 data/武昌区.shp，原始数据的坐标系: GEOGCS[\"GCS_CGCS_2000\",DATUM[\"D_2000\",SPHEROID[\"S_2000\",6378137,298.257222101004]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433],AXIS[\"Longitude\",EAST],AXIS[\"Latitude\",NORTH]]\n",
      "原始数据的坐标系: GEOGCS[\"GCS_CGCS_2000\",DATUM[\"D_2000\",SPHEROID[\"S_2000\",6378137,298.257222101004]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.0174532925199433],AXIS[\"Longitude\",EAST],AXIS[\"Latitude\",NORTH]]\n",
      "转换后数据的坐标系: EPSG:3857\n",
      "已将 data/武昌区.shp 转换后的文件保存至 data\\武昌区_3857.shp\n"
     ]
    }
   ],
   "source": [
    "vector_file_path =r'data/武昌区.shp'\n",
    "target_epsg = 'EPSG:3857'\n",
    "TransferProjByEPSG(vector_file_path,target_epsg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2840f887-be12-414f-b5d5-6cf97c84d6b2",
   "metadata": {},
   "source": [
    "#### 2.2武昌区的KFC店POI点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "109af91f-b8dc-4ded-b1da-b51570c8a884",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在处理文件 data/KFC.shp，原始数据的坐标系: EPSG:4326\n",
      "原始数据的坐标系: EPSG:4326\n",
      "转换后数据的坐标系: EPSG:3857\n",
      "已将 data/KFC.shp 转换后的文件保存至 data\\KFC_3857.shp\n"
     ]
    }
   ],
   "source": [
    "vector_file_path =r'data/KFC.shp'\n",
    "target_epsg = 'EPSG:3857'\n",
    "TransferProjByEPSG(vector_file_path,target_epsg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "653fbac4-426b-4271-8501-b5d2e74dc7b6",
   "metadata": {},
   "source": [
    "#### 2.3武昌区所有的McDonalds店POI点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "3e935fa8-3da9-46bf-885b-121509502c53",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在处理文件 data/McDonalds.shp，原始数据的坐标系: EPSG:4326\n",
      "原始数据的坐标系: EPSG:4326\n",
      "转换后数据的坐标系: EPSG:3857\n",
      "已将 data/McDonalds.shp 转换后的文件保存至 data\\McDonalds_3857.shp\n"
     ]
    }
   ],
   "source": [
    "vector_file_path =r'data/McDonalds.shp'\n",
    "target_epsg = 'EPSG:3857'\n",
    "TransferProjByEPSG(vector_file_path,target_epsg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76097e2a-4faf-48ff-ba5a-f63173b9282e",
   "metadata": {},
   "source": [
    "### 3.调用批处理转投影函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "15911bc9-1648-4ae1-b514-fe376843823e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在处理文件 data\\hubu_create.shp，原始数据的坐标系: EPSG:4326\n",
      "原始数据的坐标系: EPSG:4326\n",
      "转换后数据的坐标系: EPSG:3857\n",
      "已将 data\\hubu_create.shp 转换后的文件保存至 data\\hubu_create_3857.shp\n",
      "正在处理文件 data\\hubu_create_transfer.shp，原始数据的坐标系: EPSG:4326\n",
      "原始数据的坐标系: EPSG:4326\n",
      "转换后数据的坐标系: EPSG:3857\n",
      "已将 data\\hubu_create_transfer.shp 转换后的文件保存至 data\\hubu_create_transfer_3857.shp\n",
      "data\\JHPlain_C_Filter.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JHPlain_C_Filter_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JH_SpatialFilter.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JH_SpatialFilter_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JH_SQL_Attribute_Filter.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JH_SQL_Attribute_Filter_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JH_SQL_Filter.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JH_SQL_Filter_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JianghanPlain_C.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\JianghanPlain_C_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\KFC.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\KFC_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\McDonalds.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\McDonalds_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "正在处理文件 data\\ne_110m_admin_0_countries.shp，原始数据的坐标系: EPSG:4326\n",
      "原始数据的坐标系: EPSG:4326\n",
      "转换后数据的坐标系: EPSG:3857\n",
      "已将 data\\ne_110m_admin_0_countries.shp 转换后的文件保存至 data\\ne_110m_admin_0_countries_3857.shp\n",
      "data\\sample1m.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\sample1m_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\Search_Polygon.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\Search_Polygon_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\武昌区.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n",
      "data\\武昌区_3857.shp 已满足目标投影相关条件，跳过该文件的投影转换。\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 328239523 of field POP_EST of feature 4 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 270625568 of field POP_EST of feature 8 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 144373535 of field POP_EST of feature 18 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 127575529 of field POP_EST of feature 27 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 211049527 of field POP_EST of feature 29 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 200963599 of field POP_EST of feature 56 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 1366417754 of field POP_EST of feature 98 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 163046161 of field POP_EST of feature 99 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 216565318 of field POP_EST of feature 102 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 1397715000 of field POP_EST of feature 139 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 108116615 of field POP_EST of feature 147 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 126264931 of field POP_EST of feature 155 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 100388073 of field POP_EST of feature 163 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n",
      "d:\\GitHub\\GeoBigDataPy313\\.venv\\Lib\\site-packages\\pyogrio\\raw.py:723: RuntimeWarning: Value 112078730 of field POP_EST of feature 165 not successfully written. Possibly due to too larger number with respect to field width\n",
      "  ogr_write(\n"
     ]
    }
   ],
   "source": [
    "input_folder=r'data'\n",
    "target_epsg = 'EPSG:3857'\n",
    "batch_TransferProjByEPSG(input_folder,target_epsg)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
